<?php
/**
 * Created by PhpStorm.
 * User: ownfi
 * Date: 2017-04-08
 * Time: 10:28
 */

namespace App\Services\Impl;


use App\Common\Constant\Params;
use App\Common\Constant\Status;
use App\Events\MasterAssureFund;
use App\Models\MasterFund;
use App\Models\MasterTradeLog;
use App\Models\MasterWallet;
use App\Services\Factory\PaymentFactory;
use App\Services\IMasterLogService;
use App\Services\IPayService;
use App\Services\ISystemService;
use App\Services\IWalletService;
use DB;
use Log;

class PayServiceImpl implements IPayService
{
    private $pay_method;
    private $payer;

    private $masterLogService;

    /**
     * PayServiceImpl constructor.
     */
    public function __construct(IMasterLogService $masterLogService)
    {
        $this->masterLogService = $masterLogService;
    }


    public function setPaymentMethod($payment_method)
    {
        $this->pay_method = $payment_method;
        $this->payer = PaymentFactory::factory($payment_method);
    }

    public function assureFundOrderForm($master_id,$amount,$redirect_url)
    {
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }

        $fundOrder = resolve(IWalletService::class)->genAssureFundOrder($master_id,$amount);
        if (!$fundOrder){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'assure fund order create fail'));
            return false;
        }
        $trade_log = $this->masterLogService->PayAssureFundLog($fundOrder,$this->pay_method);
        if (!$fundOrder){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'assure fund trade log create fail'));
            return false;
        }

        return $this->payer->form($trade_log->trade_number, $fundOrder->amount, $redirect_url, Params::$TRADE_TYPE[Params::TRADE_TYPE_ASSURE],[
            'order_type'=>Params::TRADE_TYPE_ASSURE,
            'pay_method'=>$this->pay_method,
            'payer_type'=>Params::USER_TYPE_MASTER,
        ]);

    }

    public function log($message)
    {
        if (empty($this->payer)){
            throw new \Exception(status(Status::PAYMENT_METHOD_NOTSET));
        }
        $this->payer->log($message);
    }

    public function handleNotify()
    {
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }
        $this->log('1.Begin handle callback');
        list($trade_number,$payment_gate_number,$attach) = $this->payer->notify();//此处返回支付成功状态下的数据，并且已经把回调结果打印出来
        $this->log('trade_number: '.$trade_number.' payment_gate_number: '.$payment_gate_number.' attach: '.$attach);
        if (empty($trade_number) || empty($payment_gate_number)){
            $this->log('Handle callback fail!');
            return false;
        }else{
            $this->log('Handle callback success!');
            $trade_log = MasterTradeLog::where('trade_number',$trade_number)->first();
            if (!$trade_log){
                $this->log('Miss trade log');
                return false;
            }

            $this->log('4.Begin handle success payment');
//            $attach = json_decode($attach);
            $trade_log->transaction_id = $payment_gate_number;
            $trade_log->status = Params::TRADE_STATUS_SUCCESS;
            return $trade_log->save() && $this->handlePaymentSuccess($trade_number);
        }
    }

    public function checkPaymentSuccess($trade_number)
    {
        $this->log('1.Checking payment');
        $trade_log = MasterTradeLog::where('trade_number',$trade_number)->first();
        if (!$trade_log){
            $this->log('Miss trade log');
            return false;
        }
        if ($trade_log->status != Params::TRADE_STATUS_SUCCESS){
            $this->log('Trade log not success');
            return false;
        }
        $this->log('2.Begin handle success payment');
        return $this->handlePaymentSuccess($trade_number);
    }

    public function handlePaymentSuccess($trade_number)
    {
        $this->log('Handling payment');
        $trade_log = MasterTradeLog::where('trade_number',$trade_number)->first();
        if (!$trade_log){
            $this->log('Miss trade log');
            return false;
        }
        if ($trade_log->status != Params::TRADE_STATUS_SUCCESS){
            $trade_log->status = Params::TRADE_STATUS_SUCCESS;
            $trade_log->save();
        }
        $this->log('Trade log data: '.$trade_log->toJson());

        $ret = false;
        switch ($trade_log->type){
            case Params::TRADE_TYPE_ASSURE://缴纳诚信保证金
                $fundOrder = MasterFund::find($trade_log->order_number);
                if (empty($fundOrder) || ($fundOrder->status == Params::ORDER_STATUS_PAID)){
                    $ret = true;
                }else{
                    $ret = $fundOrder->update([
                            'status'=>Params::ORDER_STATUS_PAID,
                            'pay_time'=>time()
                        ])
                        && resolve(IWalletService::class)->raiseAssureFund($trade_log->id,$trade_log->master_id,$trade_log->amount)
                        && event(new MasterAssureFund($fundOrder->id));
                }
                break;
            case Params::TRADE_TYPE_ORDER://订单完成收款入账
                break;
            case Params::TRADE_TYPE_CASH://提现
                break;
            case Params::TRADE_TYPE_REFUND://商家要求退款
                break;
            case Params::TRADE_TYPE_PUNISH://罚款
                break;
            default:
                DB::rollBack();
                return false;
        }

        if ($ret){
            $this->log('Handling payment success');
        }else{
            $this->log('Handling payment fail');
        }

        return $ret;
    }

}